Dentro del módulo de Open Data del Máster de Big Data y analítica de la UNED, hemos visto muchos ejemplos de como incorporar y trabajar para contestar preguntas del día a día con datos abiertos, accesibles a todo el mundo de forma gratuita.
En este trabajo vamos a tratar de aclarar mediante representación visual de los datos, la relación del precio de la energía con la generación eléctrica por medio de fuentes renovables y no renovables.
# Nos aseguramos que están instalado los paquetes y, sino los instalamos
if(!is.element("rmarkdown", installed.packages()[, 1]))
install.packages("rmarkdown", repos = 'http://cran.us.r-project.org')
if(!is.element("rmarkdown", installed.packages()[, 1]))
install.packages("rmarkdown", repos = 'http://cran.us.r-project.org')
if(!is.element("httr", installed.packages()[, 1]))
install.packages("httr", repos = 'http://cran.us.r-project.org')
if(!is.element("jsonlite", installed.packages()[, 1]))
install.packages("jsonlite", repos = 'http://cran.us.r-project.org')
if(!is.element("ggplot2", installed.packages()[, 1]))
install.packages("ggplot2", repos = 'http://cran.us.r-project.org')
if(!is.element("httr", installed.packages()[, 1]))
install.packages("dplyr", repos = 'http://cran.us.r-project.org')
if(!is.element("ggmosaic", installed.packages()[, 1]))
install.packages("ggmosaic", repos = 'http://cran.us.r-project.org')
# Cargamos las librerías
library(rmarkdown)
library(httr)
library(jsonlite)
library(ggplot2)
library(dplyr)##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
library(ggmosaic)Voy a hacer uso del API REST que ofrece Red Eléctrica Española - REE
En las pruebas realizadas, se observan aleatorias indisponibilidades del API, para paliar ese hecho cada vez que se ejecute guarda los datos descargados, y en caso de error de descarga utilizara los últimos datos que haya descargado, como los últimos disponibles.
Cargamos los datos del API de Red Eléctrica, y lo salvaguardamos en un fichero de objeto, que en caso de error podamos volver a cargar para ejecutar los trabajos siempre con los últimos datos disponibles.
URLBaseMercadosPrecio <- "https://apidatos.ree.es/es/datos/mercados/precios-mercados-tiempo-real"
URLBaseGeneracionRenoYno <- "https://apidatos.ree.es/es/datos/generacion/evolucion-renovable-no-renovable"
dia_ayer <- format(as.Date(Sys.Date(), "%Y-%m-%dT%H:%M")-1, "%Y-%m-%dT%H:%M")
dia_menos_mes <- format(as.Date(Sys.Date(), "%Y-%m-%dT%H:%M")-30, "%Y-%m-%dT%H:%M")
# Obtención y filtrado de datos de precio
DatosMercadosPrecio <- GET(URLBaseMercadosPrecio, query = list(start_date= as.character(dia_menos_mes), end_date= as.character(dia_ayer), time_trunc="hour", geo_trunc="electric_system", geo_limit="peninsular", geo_ids=8741) )
if (DatosMercadosPrecio$status_code == "200") {
print("Lectura correcta de los datos de precios")
saveRDS(DatosMercadosPrecio, file = "DatosMercadosPrecio.rds")
DatosMercadosPrecio <- fromJSON(rawToChar(DatosMercadosPrecio$content))
d_precios_dia <- DatosMercadosPrecio[["included"]][["attributes"]][["values"]][[1]] %>% select ("value", "datetime") %>% filter(between(as.Date(datetime), as.Date(dia_menos_mes),as.Date(dia_ayer)))
} else {
print("Los datos de precios no se descargarón correctamente. Utilizando los últimos datos disponibles")
DatosMercadosPrecioreadRDS(file = "DatosMercadosPrecio.rds")
DatosMercadosPrecio <- fromJSON(rawToChar(DatosMercadosPrecio$content))
# En caso de lectura de fichero, debemos reajustar las fechas a las inluidas en el objeto
dia_ayer <- format(as.Date(DatosMercadosPrecio[["data"]][["attributes"]][["last-update"]]), "%Y-%m-%dT%H:%M")
dia_menos_mes <- format(as.Date(DatosMercadosPrecio[["data"]][["attributes"]][["last-update"]])-30, "%Y-%m-%dT%H:%M")
d_precios_dia <- DatosMercadosPrecio[["included"]][["attributes"]][["values"]][[1]] %>% select ("value", "datetime") %>% filter(between(as.Date(datetime), as.Date(dia_menos_mes),as.Date(dia_ayer)))
}## [1] "Lectura correcta de los datos de precios"
# Obtención y filtrado de datos de generación
DatosGeneracionRenoYno <- GET(URLBaseGeneracionRenoYno, query = list(start_date= as.character(dia_menos_mes), end_date= as.character(dia_ayer), time_trunc="day", geo_trunc="electric_system", geo_limit="peninsular", geo_ids=8741) )
if (DatosGeneracionRenoYno$status_code == "200") {
print("Lectura correcta de los datos de generación")
saveRDS(DatosGeneracionRenoYno, file = "DatosGeneracionRenoYno.rds")
DatosGeneracionRenoYno <- fromJSON(rawToChar(DatosGeneracionRenoYno$content))
d_gen_ren <- DatosGeneracionRenoYno[["included"]][["attributes"]][["values"]][[1]] %>% select("value", "datetime") %>% filter(between(as.Date(datetime), as.Date(dia_menos_mes),as.Date(dia_ayer)))
d_gen_NOren <- DatosGeneracionRenoYno[["included"]][["attributes"]][["values"]][[2]] %>% select("value", "datetime") %>% filter(between(as.Date(datetime), as.Date(dia_menos_mes),as.Date(dia_ayer)))
} else {
print("Los datos de generación no se descargarón correctamente. Utilizando los últimos datos disponibles")
DatosGeneracionRenoYno <- readRDS(file = "DatosGeneracionRenoYno.rds")
DatosGeneracionRenoYno <- fromJSON(rawToChar(DatosGeneracionRenoYno$content))
# En caso de lectura de fichero, debemos reajustar las fechas a las inluidas en el objeto
dia_ayer <- format(as.Date(DatosGeneracionRenoYno[["data"]][["attributes"]][["last-update"]]), "%Y-%m-%dT%H:%M")
dia_menos_mes <- format(as.Date(DatosGeneracionRenoYno[["data"]][["attributes"]][["last-update"]])-30, "%Y-%m-%dT%H:%M")
gen_ren <- DatosGeneracionRenoYno[["included"]][["attributes"]][["values"]][[1]] %>% select("value", "datetime") %>% filter(between(as.Date(datetime), as.Date(dia_menosmes),as.Date(dia_ayer)))
gen_NOren <- DatosGeneracionRenoYno[["included"]][["attributes"]][["values"]][[2]] %>% select("value", "datetime") %>% filter(between(as.Date(datetime), as.Date(dia_menosmes),as.Date(dia_ayer)))
}## [1] "Lectura correcta de los datos de generación"
Con los datos que ya hemos extraído, vamos a construir un data frame que combine los distintos orígenes de datos para posteriormente poder procesarlos con más facilidad.
fecha_simple <- as.vector(format(as.Date(d_precios_dia$datetime, "%Y-%m-%dT%H:%M"), "%Y-%m-%d"))
d_precios_dia <- cbind(d_precios_dia,fecha_simple)
# Construimos la media de precios por día pues los obtenemos por hora
d_precios_dia_media <- d_precios_dia %>% select(value, fecha_simple) %>% group_by(fecha_simple) %>% summarise(mediaXdia=mean(value))
# fecha <- format(as.Date(DatosGeneracionRenoYno[["included"]][["attributes"]][["values"]][[1]][["datetime"]], "%Y-%m-%dT%H:%M"), "%Y-%m-%d")
# Trasformamos los GW para que puedan ser visualizados en una magnitud comparable al coste
d_gen_ren <- d_gen_ren$value/1000
d_gen_NOren <- d_gen_NOren$value/1000
#creamos el dataset con todos los datos combinados que necesitamos para la representación
df_preciosXtec <- data.frame(d_precios_dia_media, # Datos Fecha - Coste
d_gen_ren, # Datos Generación Renovable
d_gen_NOren) # Datos Generación No Renovable
#eliminamos la última fila del dataset por no estar actualizados los datos de generación para ese último día.
df_preciosXtec=df_preciosXtec[-30,]
df_preciosXtec## fecha_simple mediaXdia d_gen_ren d_gen_NOren
## 1 2022-06-06 274.5108 285.7533 373.3814
## 2 2022-06-07 267.6883 281.9620 431.0802
## 3 2022-06-08 259.3062 338.3779 413.4808
## 4 2022-06-09 255.9921 353.6563 404.8968
## 5 2022-06-10 271.9421 305.7402 387.4753
## 6 2022-06-11 237.4700 357.2810 310.8538
## 7 2022-06-12 215.6996 368.2847 292.4243
## 8 2022-06-13 279.3775 335.9302 426.9668
## 9 2022-06-14 291.5729 267.7517 539.1439
## 10 2022-06-15 306.5896 260.0796 597.4280
## 11 2022-06-16 349.9004 243.5608 616.3493
## 12 2022-06-17 356.9767 271.7163 578.3887
## 13 2022-06-18 264.4971 348.2394 433.6625
## 14 2022-06-19 231.9750 369.0415 356.7351
## 15 2022-06-20 350.4608 271.9574 504.3416
## 16 2022-06-21 364.1917 246.2873 549.8496
## 17 2022-06-22 372.3279 225.6470 556.9114
## 18 2022-06-23 364.4671 253.1954 540.7726
## 19 2022-06-24 315.6217 324.1864 403.8388
## 20 2022-06-25 265.3375 296.4447 388.9532
## 21 2022-06-26 229.9217 301.0036 337.4303
## 22 2022-06-27 280.6992 349.4216 374.0245
## 23 2022-06-28 352.5158 265.1420 484.7815
## 24 2022-06-29 306.2021 293.0716 435.7897
## 25 2022-06-30 283.6058 312.9258 403.4520
## 26 2022-07-01 312.0875 302.7783 429.2627
## 27 2022-07-02 292.4558 317.6599 386.9148
## 28 2022-07-03 272.3671 317.0362 367.9431
## 29 2022-07-04 348.4563 323.2152 450.5892
Recordemos que queríamos argumentar la respuesta a la relación entre el coste de la energía con la cantidad de energía generada por fuentes renovables y no renovables.
Como este markdown, es dinámico según cuando se descarguen los datos. Lo más normal es que veamos en la gráfica una relación directa entre menor coste de la energía, a mayor generación por fuentes renovables y al contrario aumento del precio cuando aumenta la generaaicón por fuentes no renovables.
respuesta <- ggplot(df_preciosXtec, aes(x=format(as.Date(fecha_simple), "%Y-%m-%d"))) +
geom_line(aes(y=d_gen_NOren,group=1, color = "Generación no renovable"), size= 2) +
geom_line(aes(y=d_gen_ren,group=1, color = "Generación renovable"), size= 2) +
geom_line(aes(y=mediaXdia,group=1, color = "Media Precios"), size= 3) +
labs(x = "Fecha",y = "Mw/€", title = "Generación renovable/no renovable frente a precio medio",
caption = paste("Datos de:",DatosGeneracionRenoYno[["included"]][["attributes"]][["last-update"]][1])) +
theme(axis.text.x = element_text(angle = 80, size = 8,hjust = 1, vjust = 1))+
scale_color_manual(name = "Leyenda",
values = c("Media Precios" = "#FF4500", "Generación renovable" = "#698B22", "Generación no renovable" = "#8B4726"),
labels = c("Media Precios", "Generación renovable", "Generación no renovable" ))
print(respuesta)A work by Ricardo HA
rharagon@yahoo.com